//
//  ViewController.m
//  RuntimeTestDemo
//
//  Created by yuanjiang on 2017/11/17.
//  Copyright © 2017年 YuanJiang. All rights reserved.
//

#import "ViewController.h"
#import "Person.h"
#import <objc/runtime.h>

@interface ViewController ()<UITableViewDelegate,UITableViewDataSource,UITextViewDelegate>

@property(nonatomic,copy) NSString *userInfo;

@property(nonatomic,strong) Person *personModel;

@end

//首先定义一个全局变量,用它的地址作为关联对象的key
static char associatedObjectKay;

static char associatedObjectKay2;

@implementation ViewController

/**
 runtime常用来方法缓存,数据归档(model赋值),在系统内添加属性和对象等
 */
- (void)viewDidLoad {
    [super viewDidLoad];

    [self acquireMethod];
    
    [self addProperty];
    
    [self cusTomM];
    
}

- (void)cusTomM
{
    NSLog(@"我是一个方法");
}

/**
  runtime获取属性,方法,变量,协议
 */
- (void)acquireMethod
{
    unsigned int count;
    //获取属性列表
    //利用这个属性可以实现给model赋值
    //unsigned 意思是没有正负号
    objc_property_t * propertyList = class_copyPropertyList([self class], &count);
    for (unsigned int i = 0; i< count; i++) {
        const char *propertyName = property_getName(propertyList[i]);
        NSLog(@"Person类有以下属性:%@",[NSString stringWithUTF8String:propertyName]);
    }
    
    //获取方法列表
    //查看方法调用的顺序,因为可以动态的调整方法执行的顺序
    Method *methodList = class_copyMethodList([self class], &count);
    for (unsigned int i = 0; i< count; i++) {
        Method method = methodList[i];
        NSLog(@"该类中的方法名: %@",NSStringFromSelector(method_getName(method)));
    }
    
    
    //获取成员变量列表
    //什么是成员变量:
    Ivar *ivarList = class_copyIvarList([self class], &count);
    for (unsigned int i =0; i<count; i++) {
        Ivar myivar = ivarList[i];
        const char * ivarName = ivar_getName(myivar);
        NSLog(@"ivar---- %@",[NSString stringWithUTF8String:ivarName]);
    }
    
    //获取协议列表
    __unsafe_unretained Protocol **protocolList = class_copyProtocolList([self class], &count);
    for (unsigned int i =0; i<count; i++) {
        Protocol *myprotocol = protocolList[i];
        const char *protocolNmae = protocol_getName(myprotocol);
        NSLog(@"protocol----%@",[NSString stringWithUTF8String:protocolNmae]);//因为没协议 所以count为0
    }
}


/**
 现在你准备用一个系统的类,但是系统的类不能满足你的要去,你需要额外添加一个属性
 这种情况的一般解决办法就是继承/ 类目
 但是,只增加一个属性,就去继承一个类,太麻烦
 这个时候 runtime的关联属性就好用了
 不仅可以添加属性 还可以添加任何对象
 */
- (void)addProperty
{
    //objc_setAssociatedObject(给谁添加就是谁的对象,关联对象的key,要添加的属性,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    //设置关联对象
    objc_setAssociatedObject(self, &associatedObjectKay, @"label", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    NSString *string = objc_getAssociatedObject(self, &associatedObjectKay);
    NSLog(@"AssociatedObject = %@",string);
    
    //添加对象
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 400, 300)];
    label.backgroundColor = [UIColor redColor];
    label.text = @"你好";
    objc_setAssociatedObject(self, &associatedObjectKay2, label, OBJC_ASSOCIATION_RETAIN_NONATOMIC);//获取关联对象
    
    UILabel *ceshi = objc_getAssociatedObject(self, &associatedObjectKay2);
    ceshi.textAlignment = NSTextAlignmentCenter;
    ceshi.backgroundColor = [UIColor lightGrayColor];
//    ceshi.text = string;
    [self.view addSubview:ceshi];
}

@end
